package cn.slipi.admin.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;

/**
 * InetAddress工具类，处理IP,MAC获取方法 <br>
 * MAC_address URL：http://en.wikipedia.org/wiki/MAC_address <br>
 * Http X-Forwarded-For :https://en.wikipedia.org/wiki/X-Forwarded-For<br>
 *
 * @author lee
 */
public class NetUtil {

    private static final Logger LOG = LoggerFactory.getLogger(NetUtil.class);

    /**
     * MAC地址的长度
     */
    private static final int MAC_ADDRESS_LENGTH = 16;

    /**
     * 未知host替代字符
     */
    private static final String UNKNOWN_HOST = "UnknownHost";

    /**
     * 未知字符
     */
    private static final String UNKNOWN = "unknown";

    /**
     * HTTP请求XFF头，<br>
     * 这一HTTP头一般格式如下:<br>
     * X-Forwarded-For: client1, proxy1, proxy2 <br>
     *
     * @see //https://en.wikipedia.org/wiki/X-Forwarded-For<br>
     */
    private static final String HTTP_REQUEST_X_FORWARD = "x-forwarded-for";

    /**
     * HTTP请求头反向代理字段Proxy-Client-IP
     */
    private static final String HTTP_REQUEST_PROXY_CLIENT_IP = "Proxy-Client-IP";

    /**
     * HTTP请求头反向代理字段WL-Proxy-Client-IP
     */
    private static final String HTTP_REQUEST_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";

    /**
     * 服务器的host
     */
    protected static String serverHostName = null;

    /**
     * 服务器的ip
     */
    protected static String serverIp = null;

    /**
     * 获取机器的hostName
     *
     * @return
     */
    public static String getServerHostName() {
        try {
            if (null != serverHostName) {
                return serverHostName;
            }
            serverHostName = InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            LOG.error("InetUtil.getServerHostName() has error:", e);
            serverHostName = UNKNOWN_HOST;
        }
        return serverHostName;
    }

    /**
     * 获取HTTP请求真实IP
     *
     * @param request
     * @return
     */
    public static String getRequestIp(HttpServletRequest request) {
        String ip = request.getHeader(HTTP_REQUEST_X_FORWARD);
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(HTTP_REQUEST_PROXY_CLIENT_IP);
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(HTTP_REQUEST_WL_PROXY_CLIENT_IP);
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 获取IP
     *
     * @return
     */
    public static String getServerIp() {
        try {
            if (null != serverIp) {
                return serverIp;
            }
            serverIp = InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            LOG.error("InetUtil.getServerIp() has error:", e);
            serverIp = UNKNOWN_HOST;
        }
        return serverIp;
    }

    /**
     * 获取Mac地址字符串，返回字符串格式如"00-16-3E-F1-34-C2"
     *
     * @return Mac地址
     */
    public static String getMacAddress() throws Exception {
        InetAddress inetAddress = InetAddress.getLocalHost();
        NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inetAddress);

        byte[] mac = networkInterface.getHardwareAddress();
        StringBuffer macAddressBuffer = new StringBuffer(MAC_ADDRESS_LENGTH);
        for (int i = 0; i < mac.length; i++) {
            if (i != 0) {
                macAddressBuffer.append("-");
            }
            // 字节转换为整数
            int temp = mac[i] & 0xff;
            String str = Integer.toHexString(temp);
            if (str.length() == 1) {
                macAddressBuffer.append("0" + str);
            } else {
                macAddressBuffer.append(str);
            }
        }
        return macAddressBuffer.toString();
    }

    /**
     * 前24位叫做组织唯一标志符（Organizationally Unique Identifier，即OUI）， <br>
     * 是由IEEE的注册管理机构给不同厂家分配的代码，区分了不同的厂家。<br>
     * 后24位是由厂家自己分配的，称为扩展标识符。同一个厂家生产的网卡中MAC地址后24位是不同的。<br>
     * URL：http://en.wikipedia.org/wiki/MAC_address <br>
     * <p>
     * 获取Mac的扩展标识符
     *
     * @return
     */
    public static int getMacExtId() throws Exception {
        InetAddress inetAddress = InetAddress.getLocalHost();
        NetworkInterface networkInterface = NetworkInterface.getByInetAddress(inetAddress);
        int macExtId = 0;
        byte[] mac = networkInterface.getHardwareAddress();
        // 厂商自定义的MAC长度
        int firmMac = MAC_ADDRESS_LENGTH / 2;
        int fimStartIndex = 3;
        for (int index = fimStartIndex; index < mac.length; index++) {
            // 字节转换为整数
            int temp = mac[index] & 0xff;
            macExtId |= temp << (firmMac * (firmMac - fimStartIndex - index));
        }
        return macExtId;
    }

}
